#include <iostream>
#include <vector>
#include <string>
#include <boost/filesystem.hpp>
#include "Util.hpp"

// HTML目录路径
static const std::string src_path = "HTML";
// 保存去标签后文档信息的文件路径
static const std::string info_path = "INFO/info_file.txt";
// 去标签后的文档信息分隔符
static const std::string doc_delimiter = "\3";
// 去标签后的不同文档之间的分隔符
static const std::string file_delimiter = "\n";

// 错误码
enum
{
    ENUM_FILE_ERROR = 1, // 提取路径出错
    PARSE_HTML_ERROR,    // 提取信息出错
    SAVE_INFO_ERROR      // 保存文档信息出错
};

// 文档信息
struct DocInfo
{
    std::string title;   // 文档标题
    std::string content; // 文档内容
    std::string url;     // 文档网址
};

// 获取所有HTML文件的路径
bool EnumFile(const std::string &src_path, std::vector<std::string> *files_path);
// 去标签操作
bool ParseHtml(const std::vector<std::string> &files_path, std::vector<DocInfo> *docInfos);
// 保存解析后的文档信息
bool SaveInfo(const std::vector<DocInfo> &docInfos, const std::string &info_path);

int main()
{
    // 第一步：获取所有HTML文件路径
    std::vector<std::string> files_path;
    if (!EnumFile(src_path, &files_path))
    {
        std::cerr << "enum html file path error" << std::endl;
        return ENUM_FILE_ERROR;
    }

    // 第二部：去标签操作
    std::vector<DocInfo> docInfos;
    if (!ParseHtml(files_path, &docInfos))
    {
        std::cerr << "parse html file error!" << std::endl;
        return PARSE_HTML_ERROR;
    }

    // 第三步：保存解析后的文档信息
    if (!SaveInfo(docInfos, info_path))
    {
        std::cerr << "save html file infomation error!" << std::endl;
        return SAVE_INFO_ERROR;
    }

    // //DEBUG查看docInfos中的内容
    // for(auto &docInfo : docInfos)
    // {
    //     std::cout << "title: " << docInfo.title << std::endl;
    //     std::cout << "url: " << docInfo.url << std::endl;
    //     std::string content = docInfo.content.substr(0, 100);
    //     std::cout << "content:" << content << std::endl;
    // }
    return 0;
}

// 获取所有HTML文件的路径
bool EnumFile(const std::string &src_path, std::vector<std::string> *files_path)
{
    namespace ns = boost::filesystem;
    // 构建path对象
    ns::path path(src_path);
    // 判断路径是否存在
    if (!ns::exists(path))
    {
        std::cout << "path is not exists!" << std::endl;
        return false;
    }

    // 构造一个空的迭代器
    ns::recursive_directory_iterator end;
    // 遍历src_path下的所有目录和文件
    for (ns::recursive_directory_iterator it(path); it != end; it++)
    {
        // 如果说是以.html结尾的文件就放入到files_Path中
        if (ns::is_regular_file(*it) && it->path().extension() == ".html")
        {
            files_path->push_back(it->path().string());
        }
    }
    return true;
}

// 去标签操作
bool ParseHtml(const std::vector<std::string> &files_path, std::vector<DocInfo> *docInfos)
{
    for (auto &file : files_path)
    {
        // 用于保存文件内容
        std::string file_content;
        // 读取文件内容
        if (!Util::ReadFile(file, &file_content))
        {
            return false;
        }

        // 保存文档信息对象
        DocInfo docInfo;
        // 获取文档标题
        if (!Util::ParseTitle(file_content, &docInfo.title))
        {
            return false;
        }
        // 获取文档内容
        if (!Util::ParseContent(file_content, &docInfo.content))
        {
            return false;
        }
        // 解析文档网址
        if (!Util::ParseUrl(file, &docInfo.url, src_path))
        {
            return false;
        }
        // 将构建好的docInfo对象放入到数组中
        docInfos->push_back(std::move(docInfo));
    }
    return true;
}

// 保存解析后的文档信息
bool SaveInfo(const std::vector<DocInfo> &docInfos, const std::string &info_path)
{
    // 按照 title\3content\3url\n 的形式写入文档
    // 以二进制写入的方式打开文档
    std::ofstream out(info_path, std::ios::binary);

    // 判断是否打开成功
    if (!out.is_open())
    {
        return false;
    }
    // 遍历写入文件
    for (auto &docInfo : docInfos)
    {
        // 构建一个文档的信息字符串
        std::string info = docInfo.title;
        info += doc_delimiter;

        info += docInfo.content;
        info += doc_delimiter;

        info += docInfo.url;
        info += file_delimiter;

        // 写入到文件当中
        out.write(info.c_str(), info.size());
    }
    return true;
}